package com.diy.sigmund.diycommon.designpatterns.singlecasemodel;

/**
 * javap InnerEnumClass$InnerClass.class
 *
 * Compiled from "InnerEnumClass.java"
 * final class com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass$InnerClass extends java.lang.Enum<com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass$InnerClass> {
 * public static final com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass$InnerClass INSTANCE;
 * public static com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass$InnerClass[] values();
 * public static com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass$InnerClass valueOf(java.lang.String);
 * public com.diy.sigmund.diycommon.designpatterns.singlecasemodel.InnerEnumClass getInstance();
 * static {};
 * }
 *
 * 从枚举的反编译结果可以看到，INSTANCE被static final修饰，所以可以直接通过类名调用，
 * 并且创建对象的实例是在静态代码块中创建的，因为static类型的属性会在类被加载之后被初始化，
 * 当一个Java类第一次被真正使用到的时候静态资源被初始化，Java类的加载和初始化过程都是线程安全的，
 * 所以创建一个enum类型是线程安全的。
 *
 * 内部枚举类实现单例
 *
 * @author ylm-sigmund
 * @since 2021/8/16 17:57
 */
public class InnerEnumClass {

    /** 构造方法私有化 */
    private InnerEnumClass() {
    }

    /** 返回实例 */
    public static InnerEnumClass getInstance() {
        return InnerClass.INSTANCE.getInstance();
    }

    /** 内部枚举类 */
    private enum InnerClass {
        /** 实例枚举 */
        INSTANCE;
        private InnerEnumClass instance;

        /** JVM保证这个方法只调用一次 */
        InnerClass() {
            instance = new InnerEnumClass();
        }

        public InnerEnumClass getInstance() {
            return instance;
        }
    }

    /**
     * 测试ok
     */
    public static void main(String[] args) {
        final InnerEnumClass instance = InnerEnumClass.getInstance();
        final InnerEnumClass instance1 = InnerEnumClass.getInstance();
        System.out.println(instance1 == instance);
    }
}
